package com.zhongkun.datahome.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zhongkun.datahome.common.constant.HttpStatus;
import com.zhongkun.datahome.common.core.domain.entity.TenantUser;
import com.zhongkun.datahome.common.core.domain.model.LoginUser;
import com.zhongkun.datahome.common.exception.ServiceException;
import com.zhongkun.datahome.common.utils.SecurityUtils;
import com.zhongkun.datahome.core.domain.vo.UserBaseVo;
import com.zhongkun.datahome.core.repository.TenantUserRepository;
import com.zhongkun.datahome.core.req.qry.user.UserQry;
import com.zhongkun.datahome.core.service.ISysUserService;
import com.zhongkun.datahome.framework.manager.AsyncManager;
import com.zhongkun.datahome.service.constant.YesOrNoEnum;
import com.zhongkun.datahome.service.domain.CustomerBase;
import com.zhongkun.datahome.service.domain.CustomerFamily;
import com.zhongkun.datahome.service.domain.CustomerHouse;
import com.zhongkun.datahome.service.domain.HouseBuildPlan;
import com.zhongkun.datahome.service.domain.HouseServerRelation;
import com.zhongkun.datahome.service.manager.ServiceAsyncFactory;
import com.zhongkun.datahome.service.mapper.MiniProgramNodeSettingMapper;
import com.zhongkun.datahome.service.repository.CustomerBaseRepository;
import com.zhongkun.datahome.service.repository.CustomerFamilyRepository;
import com.zhongkun.datahome.service.repository.CustomerHouseRepository;
import com.zhongkun.datahome.service.repository.HouseBuildPlanRepository;
import com.zhongkun.datahome.service.repository.HouseMaterialRepository;
import com.zhongkun.datahome.service.repository.HouseServerRelationRepository;
import com.zhongkun.datahome.service.req.cmd.customer.CustomerBaseCmd;
import com.zhongkun.datahome.service.req.cmd.house.CustomerHouseCmd;
import com.zhongkun.datahome.service.req.cmd.house.CustomerHouseServerCmd;
import com.zhongkun.datahome.service.req.cmd.system.MiniProgramNodeSettingCmd;
import com.zhongkun.datahome.service.req.qry.house.CustomerHouseQry;
import com.zhongkun.datahome.service.res.PageVo;
import com.zhongkun.datahome.service.res.house.CustomerHouseAppVo;
import com.zhongkun.datahome.service.res.house.CustomerHouseDetailVo;
import com.zhongkun.datahome.service.res.house.CustomerHouseSelectVo;
import com.zhongkun.datahome.service.res.house.CustomerHouseVo;
import com.zhongkun.datahome.service.service.ICustomerBaseService;
import com.zhongkun.datahome.service.service.ICustomerHouseService;
import com.zhongkun.datahome.service.service.IWeixinService;
import com.zhongkun.datahome.service.utils.StreamUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 客户房产Service业务层处理
 *
 * @author ruoyi
 * @date 2025-04-14
 */
@Service
@Slf4j
public class CustomerHouseServiceImpl implements ICustomerHouseService {
    @Resource
    private ISysUserService sysUserService;

    @Resource
    private CustomerHouseRepository customerHouseRepository;

    @Resource
    private CustomerBaseRepository customerBaseRepository;

    @Resource
    private HouseServerRelationRepository houseServerRelationRepository;

    @Resource
    private HouseBuildPlanRepository houseBuildPlanRepository;

    @Resource
    private HouseMaterialRepository houseMaterialRepository;

    @Resource
    private ICustomerBaseService customerBaseService;

    @Resource
    private IWeixinService weixinService;

    @Resource
    private MiniProgramNodeSettingMapper miniProgramNodeSettingMapper;

    @Resource
    private CustomerFamilyRepository customerFamilyRepository;

    @Resource
    private TenantUserRepository tenantUserRepository;


    @Override
    public PageVo<CustomerHouseVo> page(CustomerHouseQry qry) {
        IPage<CustomerHouseVo> page = customerHouseRepository.pageCustomerHouseVo(qry);
        return PageVo.of(page);
    }

    @Override
    public CustomerHouseDetailVo getInfo(Long id) {
        // 房产基本信息
        CustomerHouse customerHouse = customerHouseRepository.getById(id);
        if (Objects.isNull(customerHouse)) {
            throw new ServiceException("房产不存在");
        }

        // 家庭成员
        List<CustomerBase> memberInfo = customerBaseRepository.getMemberByFamilyId(customerHouse.getFamilyId());

        // 服务团队
        List<Long> serverUserIds = houseServerRelationRepository.listServerUserId(id);
        List<UserBaseVo> serverUserBaseVos = CollectionUtils.isEmpty(serverUserIds)
                ? Collections.emptyList() : sysUserService.listUserInfo(UserQry.of(serverUserIds));

        return CustomerHouseDetailVo.of(customerHouse, memberInfo, serverUserBaseVos);
    }

    @Override
    @Transactional
    public Long add(CustomerHouseCmd cmd) {
        checkHouseRoomExist(cmd.getBuildingNum(), cmd.getRoomNum(), cmd.getId());
        // 保存客户
        CustomerBase customerBase = customerBaseService.save(CustomerBaseCmd.of(cmd));

        // 新建房产
        CustomerHouse customerHouse = CustomerHouse.of(cmd);
        customerHouse.setSource("back_add");
        customerHouse.setFamilyId(customerBase.getFamilyId());

        customerHouseRepository.save(customerHouse);

        // 保存配置的默认节点
        List<MiniProgramNodeSettingCmd> miniProgramNodeSettings = miniProgramNodeSettingMapper.queryNodeList();
        if (CollectionUtils.isNotEmpty(miniProgramNodeSettings)) {
            List<HouseBuildPlan> houseBuildPlans = miniProgramNodeSettings.stream()
                    .map(item -> HouseBuildPlan.of(customerHouse.getId(), item))
                    .collect(Collectors.toList());
            houseBuildPlanRepository.saveBatch(houseBuildPlans);
        }

        AsyncManager.me().execute(ServiceAsyncFactory.createCustomerMiniProgram(customerHouse.getId()));
        return customerHouse.getId();
    }

    private void checkHouseRoomExist(String buildingNum, String roomNum, Long id) {
        CustomerHouse customerHouse = customerHouseRepository.checkHouseRoomExist(buildingNum, roomNum, id);
        if (Objects.nonNull(customerHouse)) {
            throw new ServiceException(MessageFormat.format("该房产{0}-{1}已存在，请勿重复添加", buildingNum, roomNum));
        }
    }

    @Override
    @Transactional
    public void edit(CustomerHouseCmd cmd) {
        checkHouseRoomExist(cmd.getBuildingNum(), cmd.getRoomNum(), cmd.getId());
        CustomerHouse customerHouse = customerHouseRepository.getById(cmd.getId());
        if (Objects.isNull(customerHouse)) {
            throw new ServiceException("房产不存在");
        }

        // 保存客户
        CustomerBase customerBase = customerBaseService.save(CustomerBaseCmd.of(cmd));

        customerHouse.update(cmd);
        customerHouse.setFamilyId(customerBase.getFamilyId());
        customerHouseRepository.updateById(customerHouse);
    }

    @Override
    @Transactional
    public void remove(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        for (Long customerHouseId : ids) {
            CustomerHouse customerHouse = customerHouseRepository.getById(customerHouseId);
            customerHouseRepository.removeById(customerHouseId);
            houseServerRelationRepository.removeByHouseIds(List.of(customerHouseId));
            houseBuildPlanRepository.removeByHouseIds(List.of(customerHouseId));
            houseMaterialRepository.removeByHouseIds(List.of(customerHouseId));

            List<CustomerHouse> customerHouseList = customerHouseRepository.listByFamilyId(customerHouse.getFamilyId());
            if (CollectionUtils.isEmpty(customerHouseList)) {
                //删除家庭
                customerFamilyRepository.removeById(customerHouse.getFamilyId());

                customerBaseService.removeByFamilyId(customerHouse.getFamilyId());
            }


        }

    }

    @Override
    public void addServer(CustomerHouseServerCmd cmd) {
        List<HouseServerRelation> relations = houseServerRelationRepository.listBy(cmd.getHouseId(), cmd.getTenantUserId());
        if (CollectionUtils.isNotEmpty(relations)) {
            throw new ServiceException("该房产已添加该服务人员");
        }

        houseServerRelationRepository.save(HouseServerRelation.of(cmd.getHouseId(), cmd.getTenantUserId()));
    }

    @Override
    public void delServer(CustomerHouseServerCmd cmd) {
        houseServerRelationRepository.removeBy(cmd.getHouseId(), cmd.getTenantUserId());
    }

    @Override
    public void updateCustomerHouseMiniProgram(Long customerHouseId) {
        String customerMiniProgram = weixinService.getCustomerMiniProgram(customerHouseId);
        CustomerHouse customerHouse = customerHouseRepository.getById(customerHouseId);
        customerHouse.setMiniProgramImg(customerMiniProgram);
        customerHouseRepository.updateById(customerHouse);
    }

    @Override
    public List<CustomerHouseAppVo> listHouseInfoForApp(String roomNum, boolean employeeFlag) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (Objects.isNull(loginUser) || Objects.isNull(loginUser.getUser())) {
            throw new ServiceException("用户未登陆");
        }

        List<CustomerHouse> customerHouses = null;

        // 管理员展示商户全部房产，员工需要展示关联服务的相关房产，非员工（客户）只展示自有房产
        if (employeeFlag && loginUser.getUser().hasAdminRole()) {
            customerHouses = customerHouseRepository.list(roomNum);
        } else if (employeeFlag && !loginUser.getUser().hasAdminRole()) {
            customerHouses = customerHouseRepository.listHouseByServerTenantUserId(loginUser.getTenantUserId(), roomNum);
        } else {
            customerHouses = customerHouseRepository.listByTenantUserId(loginUser.getTenantUserId());
        }

        return getHouseDetails(customerHouses, employeeFlag);
    }

    @Override
    public CustomerHouseAppVo getHouseInfoForApp(Long houseId) {
        CustomerHouse customerHouse = customerHouseRepository.getById(houseId);
        if (Objects.isNull(customerHouse)) {
            throw new ServiceException("房产不存在");
        }

        // 校验访问权限
        checkPermission(customerHouse);
        boolean employeeFlag = SecurityUtils.getLoginUser().getUser().isEmployee();
        return getHouseDetails(List.of(customerHouse), employeeFlag).stream().findFirst().orElse(null);
    }

    private void checkPermission(CustomerHouse customerHouse) {
        if (SecurityUtils.getLoginUser().getUser().isAdminEmployee()) {
            return;
        }

        List<Long> serverUserIdList = houseServerRelationRepository.listServerUserId(customerHouse.getId());
        if (serverUserIdList.stream().noneMatch(serverUserId -> serverUserId.equals(SecurityUtils.getLoginUser().getTenantUserId()))) {
            throw new ServiceException("您无权限查看该信息", HttpStatus.WARN);
        }
    }

    private List<CustomerHouseAppVo> getHouseDetails(List<CustomerHouse> customerHouses, boolean employeeFlag) {
        List<Long> showBuildPlanHouseIds = customerHouses.stream()
                .filter(item -> employeeFlag || YesOrNoEnum.YES.is(item.getBuildPlanShowFlag()))
                .map(CustomerHouse::getId)
                .collect(Collectors.toList());

        Map<Long, List<HouseBuildPlan>> buildPlanMap = houseBuildPlanRepository.getMap(showBuildPlanHouseIds);

        return customerHouses.stream()
                .map(item -> CustomerHouseAppVo.of(item, buildPlanMap.getOrDefault(item.getId(), Collections.emptyList())))
                .collect(Collectors.toList());
    }

    @Override
    public List<CustomerHouseSelectVo> selectHouseInfo(String roomNum) {
        List<CustomerHouse> list = customerHouseRepository.getLike(null, roomNum);
        Map<String, List<CustomerHouse>> buildingNumGroupMap = StreamUtil.listGroupBy(list, CustomerHouse::getBuildingNum);

        List<CustomerHouseSelectVo> customerHouseSelectVos = new ArrayList<>();
        buildingNumGroupMap.forEach((buildingNum, customerHouses) -> customerHouseSelectVos.add(CustomerHouseSelectVo.of(customerHouses, buildingNum)));
        customerHouseSelectVos.sort(Comparator.comparing(CustomerHouseSelectVo::getBuildingNum));
        customerHouseSelectVos.forEach(item -> item.getHouseList().sort(Comparator.comparing(CustomerHouseSelectVo.HouseSelectVo::getRoomNum)));
        return customerHouseSelectVos;
    }

    @Override
    public void fillAllCustomerHouseImg() {
        List<CustomerHouse> customerHouseList = customerHouseRepository.list();
        for (CustomerHouse customerHouse : customerHouseList) {
            if (Objects.isNull(customerHouse.getMiniProgramImg())) {
                AsyncManager.me().execute(ServiceAsyncFactory.createCustomerMiniProgram(customerHouse.getId()));
            }
        }
    }

    @Override
    @Transactional
    public void deleteByUserIdList(List<Long> userIdList) {
        userIdList.forEach(this::deleteByUserId);
    }

    @Transactional
    public void deleteByUserId(Long userId) {
        TenantUser tenantUser = tenantUserRepository.getOne(new LambdaQueryWrapper<TenantUser>().eq(TenantUser::getUserId, userId).eq(TenantUser::getTenantId, SecurityUtils.getTenantId()), false);
        if (Objects.isNull(tenantUser)) {
            return;
        }

        CustomerBase customerBase = customerBaseRepository.getByTenantUserId(tenantUser.getId());
        if (customerBase == null) {
            return;
        }
        CustomerFamily customerFamily = customerFamilyRepository.getOne(new LambdaQueryWrapper<CustomerFamily>().eq(CustomerFamily::getOwnerCustomerId, customerBase.getId()), false);
        if (Objects.isNull(customerFamily)) {
            // 直接删除用户
            customerBaseRepository.removeById(customerBase.getId());
        } else {
            // 直接删除房产
            List<CustomerHouse> customerHouseList = customerHouseRepository.listByFamilyId(customerFamily.getId());
            remove(customerHouseList.stream().map(CustomerHouse::getId).collect(Collectors.toList()));
        }
    }
}
